<template>
  <div class="image-crop-page">
    <t-card class="crop-card">
      <div class="cropper-tip-flex">
        <span>本页面图片裁剪功能基于 cropperjs 和 vue-cropperjs 实现。</span>
        <span class="cropper-tip-link" @click="goToCropperjs" title="点击跳转 cropperjs 中文官网">点我跳转 cropperjs 中文官网</span>
      </div>
      <div class="third-cropper-root">
        <div class="btn-group">
          <input
            ref="fileInputRef"
            type="file"
            accept="image/png, image/jpeg"
            style="display: none"
            @change="onFileChange"
          />
          <t-button theme="primary" v-throttle="triggerFileInput">导入图片</t-button>
          <t-button theme="default" :disabled="!imageUrl" v-throttle="onRemoveImage">删除图片</t-button>
          <t-button theme="success" :disabled="!imageUrl" v-throttle="onExport">导出裁剪图片</t-button>
        </div>

        <div class="preview-area">
          <div v-if="imageUrl" class="cropper-container">
            <vue-cropper
              ref="cropper"
              :src="imageUrl"
              :aspect-ratio="1"
              :view-mode="1"
              :auto-crop-area="0"  
              :data="cropBoxData"
              style="width: 400px; height: 400px; display: block; margin: 0 auto;"
            />
          </div>

          <div v-else class="empty-preview">
            <t-icon name="image" size="48px" />
            <div class="empty-text">请导入图片，支持 JPG/PNG 格式，最大5MB</div>
          </div>
        </div>
      </div>
    </t-card>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import { MessagePlugin, DialogPlugin } from 'tdesign-vue-next';
import VueCropper from 'vue-cropperjs';
import 'cropperjs/dist/cropper.css';

const imageUrl = ref('');
const fileInputRef = ref<HTMLInputElement | null>(null);
const cropper = ref<any>(null);

// 默认裁剪框 150x150 居中
const cropBoxData = ref({
  width: 150,
  height: 150,
  x: 125, // (400-150)/2
  y: 125
});

// 每次图片切换时重置裁剪框
watch(imageUrl, (val) => {
  if (val) {
    cropBoxData.value = {
      width: 150,
      height: 150,
      x: 125,
      y: 125
    };
  }
});

function triggerFileInput() {
  if (fileInputRef.value) fileInputRef.value.value = '';
  fileInputRef.value?.click();
}

function beforeUpload(file: File) {
  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
  if (!isJpgOrPng) {
    MessagePlugin.error('仅支持 JPG/PNG 格式图片');
    return false;
  }
  const isLt5M = file.size / 1024 / 1024 < 5;
  if (!isLt5M) {
    MessagePlugin.error('图片大小不能超过 5MB');
    return false;
  }
  return true;
}

function onFileChange(e: Event) {
  const files = (e.target as HTMLInputElement).files;
  if (!files || !files[0]) return;
  const file = files[0];
  if (!beforeUpload(file)) {
    (e.target as HTMLInputElement).value = '';
    return;
  }

  const reader = new FileReader();
  reader.onload = (ev) => {
    imageUrl.value = ev.target?.result as string;
    if (fileInputRef.value) fileInputRef.value.value = '';
  };
  reader.readAsDataURL(file);
}

function onExport() {
  const dialog = DialogPlugin.confirm({
    header: '确认导出',
    body: '确定要导出当前裁剪区域的图片吗？',
    confirmBtn: '确定',
    cancelBtn: '取消',
    onConfirm: () => {
      if (!cropper.value) {
        MessagePlugin.warning('未找到裁剪器实例');
        dialog.hide();
        return;
      }
      const canvas = cropper.value.getCroppedCanvas({
        width: 150,
        height: 150,
        imageSmoothingEnabled: true,
        imageSmoothingQuality: 'high',
      });
      if (!canvas) {
        MessagePlugin.warning('导出失败');
        dialog.hide();
        return;
      }
      canvas.toBlob((blob: Blob | null) => {
        if (!blob) {
          MessagePlugin.warning('导出失败');
          dialog.hide();
          return;
        }
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'cropped-image.png';
        a.click();
        URL.revokeObjectURL(url);
        MessagePlugin.success('图片已导出');
        dialog.hide();
      }, 'image/png');
    },
    onClose: () => dialog.hide(),
    onCancel: () => dialog.hide(),
  });
}

function onRemoveImage() {
  const dialog = DialogPlugin.confirm({
    header: '确认删除',
    body: '确定要删除当前图片吗？',
    confirmBtn: '确定',
    cancelBtn: '取消',
    onConfirm: () => {
      imageUrl.value = '';
      if (fileInputRef.value) fileInputRef.value.value = '';
      MessagePlugin.success('图片已删除');
      dialog.hide();
    },
    onClose: () => dialog.hide(),
    onCancel: () => dialog.hide(),
  });
}

// 跳转到 cropperjs 中文官网
function goToCropperjs() {
  window.open('https://fengyuanchen.github.io/cropperjs/v2/zh/', '_blank');
}
</script>

<style scoped lang="less">
.image-crop-page {
  width: 100%;
  height: 100%;
  background: var(--td-bg-color-container, #fff);
  display: flex;
  align-items: stretch;
  justify-content: stretch;
  overflow: hidden;
}

.crop-card {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  background: transparent;
  box-shadow: none;
  overflow: hidden;
}

.cropper-tip-flex {
  margin: 16px 0 0 0;
  color: #888;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.cropper-tip-link {
  color: #0052d9;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  transition: color 0.2s;
  &:hover {
    color: #1890ff;
    text-decoration: underline;
  }
}

.third-cropper-root {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.btn-group {
  display: flex;
  gap: 16px;
  margin-top: 24px;
  margin-bottom: 24px;
}

.preview-area {
  flex: 1;
  min-height: 320px;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--image-crop-preview-bg, #fafbfc);
  border-radius: 8px;
  overflow: hidden;
  position: relative;
}

:root[theme-mode='dark'] .preview-area {
  --image-crop-preview-bg: #23272e;
}
:root[theme-mode='light'] .preview-area {
  --image-crop-preview-bg: #fafbfc;
}

.cropper-container {
  width: 400px;
  height: 400px;
  max-width: 100%;
  max-height: 100%;
  margin: 0 auto;
}

.empty-preview {
  width: 50%;
  height: 50%;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #bfbfbf;
  font-size: 16px;
  gap: 12px;
}

.empty-text {
  margin-top: 8px;
  color: #bfbfbf;
}
</style>

<script lang="ts">
export default {
  name: 'ImageCrop',
};
</script>
